//***********************************************
//Project Name               :
//File Name                  :
//Author                     :ZJL
//Date of Creation           :
//Functional Description     :
//              
//Revision History           :
//Change Log                 :
//***********************************************
module window_3x3 #(
    	parameter PIX_PER_LINE = 320,
	parameter PIX_DOUBLE_LINE = 640
)(
						input 	wire    [1-1:0]		i_Clk         ,
						input 	wire    [1-1:0]		i_Frame_rst   ,
						input   wire    [16-1:0]    i_Data_in     ,
						input   wire    [1-1:0]     i_Data_vld    ,
						output  reg     [16-1:0]    o_Data_00     ,
						output  reg     [16-1:0]    o_Data_01     ,
						output  reg     [16-1:0]    o_Data_02     ,
						output  reg     [16-1:0]    o_Data_10     ,
						output  reg     [16-1:0]    o_Data_11     ,
						output  reg     [16-1:0]    o_Data_12     ,
						output  reg     [16-1:0]    o_Data_20     ,
						output  reg     [16-1:0]    o_Data_21     ,
						output  reg     [16-1:0]    o_Data_22     ,
						output  reg     [1-1:0]     o_Data_vld                
						);
						

	
wire[ 1-1: 0 ] buf1_rden;
reg line_buf_rden_d1;
wire[ 15: 0 ] dout_buf1;
wire[ 15: 0 ] dout_buf2;
wire[ 15: 0 ] dout_buf3;
wire[ 9: 0 ] buf1_data_count;
wire[ 9: 0 ] buf2_data_count;
wire[ 9: 0 ] buf3_data_count;
wire	buf2_rden;
wire	buf3_rden;
reg[ 9: 0 ] line_buf_rd_cnt;
reg[ 10: 0 ] line_rden_cnt;
reg	line_data_valid;
reg	line_data_valid_d1, line_data_valid_d2;

assign buf2_rden = ( buf2_data_count >= PIX_PER_LINE - 1 ) ? buf1_rden : 1'b0;
assign buf3_rden = ( buf3_data_count >= PIX_PER_LINE - 1 ) ? buf1_rden : 1'b0;

wire        [1-1:0]         buf_rd_add;
reg        [1-1:0]         en_cnt_buf_rd;
reg        [10-1:0]        cnt_buf_rd;
parameter                  CNT_BUF_RD = PIX_PER_LINE;
assign     buf_rd_add = (buf1_data_count >= PIX_PER_LINE);
always @ ( posedge i_Clk ) begin
    if( i_Frame_rst ) begin
        cnt_buf_rd        <=        'd0;
    end
    else if( en_cnt_buf_rd )begin//只有在有效才计数
        cnt_buf_rd        <=        cnt_buf_rd + 'd1;
    end
    else begin
        cnt_buf_rd        <=        'd0;
    end
end
        
always @ ( posedge i_Clk ) begin
    if(i_Frame_rst) begin
        en_cnt_buf_rd        <=        'd0;
    end
    else if( cnt_buf_rd == CNT_BUF_RD - 1)begin//结束计数条件
        en_cnt_buf_rd        <=        'd0;
    end
    else if( buf_rd_add )begin        //开始计数条件
        en_cnt_buf_rd        <=        'd1;
    end
    else begin
        en_cnt_buf_rd        <=        en_cnt_buf_rd;
    end
end
assign buf1_rden = en_cnt_buf_rd ;


always @( posedge i_Clk ) begin
	line_buf_rden_d1 <= buf1_rden;
end

always @( posedge i_Clk ) begin
	if ( i_Frame_rst )
		line_rden_cnt <= 11'd0;
	else if ( buf1_rden ) begin
		if ( line_rden_cnt < PIX_DOUBLE_LINE )
			line_rden_cnt <= line_rden_cnt + 1'b1;
		else
			line_rden_cnt <= line_rden_cnt;
	end
	else
		line_rden_cnt <= line_rden_cnt;
end

always @( posedge i_Clk ) begin
	if ( i_Frame_rst )
		line_data_valid <= 1'b0;
	else if ( line_rden_cnt == PIX_DOUBLE_LINE )
		line_data_valid <= buf1_rden;
	else
		line_data_valid <= 1'b0;
end

always @( posedge i_Clk ) begin
	if ( i_Frame_rst ) begin
		o_Data_00 <= 16'h0;
		o_Data_01 <= 16'h0;
		o_Data_02 <= 16'h0;

		o_Data_10 <= 16'h0;
		o_Data_11 <= 16'h0;
		o_Data_12 <= 16'h0;

		o_Data_20 <= 16'h0;
		o_Data_21 <= 16'h0;
		o_Data_22 <= 16'h0;

		line_data_valid_d1 <= 1'b0;
		line_data_valid_d2 <= 1'b0;
	end
	else begin
		o_Data_22 <= dout_buf1;
		o_Data_21 <= o_Data_22;
		o_Data_20 <= o_Data_21;

		o_Data_12 <= dout_buf2;
		o_Data_11 <= o_Data_12;
		o_Data_10 <= o_Data_11;

		o_Data_02 <= dout_buf3;
		o_Data_01 <= o_Data_02;
		o_Data_00 <= o_Data_01;

		line_data_valid_d1 <= line_data_valid;
		line_data_valid_d2 <= line_data_valid_d1;
		o_Data_vld	<= line_data_valid_d2;
	end
end

enfifo1024x16 inst_buf1(
				  .aclr	    ( i_Frame_rst           ),
				  .clock	( i_Clk                 ),
				  .wrreq	( i_Data_vld            ),
				  .data	    ( i_Data_in             ),
				  .q	    ( dout_buf1             ),
				  .rdreq	( buf1_rden             ),
				  .usedw	( buf1_data_count       )
			  );

enfifo1024x16 inst_buf2(
				  .aclr	    ( i_Frame_rst           ),
				  .clock	( i_Clk                 ),
				  .wrreq	( line_buf_rden_d1      ),
				  .data	    ( dout_buf1             ),
				  .q	    ( dout_buf2             ),
				  .rdreq	( buf2_rden             ),
				  .usedw	( buf2_data_count       )
			  );

enfifo1024x16 inst_buf3(
				  .aclr     ( i_Frame_rst           ),
				  .clock    ( i_Clk                 ),
				  .wrreq    ( line_buf_rden_d1      ),
				  .data     ( dout_buf2             ),
				  .q        ( dout_buf3             ),
				  .rdreq    ( buf3_rden             ),
				  .usedw    ( buf3_data_count       )
			  );
								  
endmodule 